﻿using System;
using System.Collections.Generic;
using UnityEngine;

public class QuickVarList : IDisposable
{
    List<Variant> bufArr = new List<Variant>();

    public int Position { set; get; }
    public int Length { get { return bufArr.Count; } }
    public int Count { get { return bufArr.Count; } }

    private static Stack<QuickVarList> pool = new Stack<QuickVarList>();

    public static int PoolCount { get { return pool.Count; } }


    public static QuickVarList Get()
    {
        //Debug.Assert(System.Threading.Thread.CurrentThread.ManagedThreadId == GameMain.Event.mainThreadID);

        if (pool.Count <= 0)
        {
            Debug.LogError("QuickVarList pool is null!");
            return new QuickVarList();
        }

        return pool.Pop();
    }

    public bool Contains(Variant var)
    {
        return bufArr.Contains(var);
    }

    public bool IsEmpty()
    {
        return Position >= Length;
    }

    public bool IsEnd()
    {
        return Position >= Length;
    }

    public void Clear()
    {
        Position = 0;
        bufArr.Clear();
    }

    static long PoolFreeCount = 0;
    public void Dispose()
    {
        Clear();
        if (pool.Count < 10000)
        {
            pool.Push(this);
        }
        else
        {
            ++PoolFreeCount;

            if (PoolFreeCount > 10000)
            {
                Debug.LogError("QuickVarList Pool Warnning");
                PoolFreeCount = 0;
            }

            GC.SuppressFinalize(this);
        }
    }

    public VariantType GetVarType(int index)
    {
        if (index < 0 || index >= bufArr.Count)
            return VariantType.NONE;

        return bufArr[index].type;
    }

    public Variant GetVariant(int index)
    {
        if (index < 0 || index >= bufArr.Count)
            return Variant.None;

        return bufArr[index];
    }

    public void Remove(int index_, int count)
    {
        bufArr.RemoveRange(index_, count);
    }

    public void Remove(int index_)
    {
        bufArr.RemoveAt(index_);
    }

    public bool ReadBool(int index)
    {
        return GetVariant(index).GetBool();
    }

    public double ReadDouble(int index)
    {
        return GetVariant(index).GetDouble();
    }

    public float ReadFloat(int index)
    {
        return GetVariant(index).GetFloat();
    }

    public short ReadInt16(int index)
    {
        return GetVariant(index).GetInt16();
    }

    public int ReadInt32(int index)
    {
        return GetVariant(index).GetInt32();
    }

    public long ReadInt64(int index)
    {
        return GetVariant(index).GetInt64();
    }

    public sbyte ReadInt8(int index)
    {
        return GetVariant(index).GetInt8();
    }

    public object ReadNull(int index)
    {
        return GetVariant(index).GetNull();
    }


    public string ReadString(int index)
    {
        return GetVariant(index).GetString();
    }

    public ushort ReadUInt16(int index)
    {
        return GetVariant(index).GetUInt16();
    }

    public uint ReadUInt32(int index)
    {
        return GetVariant(index).GetUInt32();
    }

    public ulong ReadUInt64(int index)
    {
        return GetVariant(index).GetUInt64();
    }

    public byte ReadUInt8(int index)
    {
        return GetVariant(index).GetUInt8();
    }

    public bool GetBool(int index)
    {
        return GetVariant(index).GetBool();
    }

    public double GetDouble(int index)
    {
        return GetVariant(index).GetDouble();
    }

    public float GetFloat(int index)
    {
        return GetVariant(index).GetFloat();
    }

    public short GetInt16(int index)
    {
        return GetVariant(index).GetInt16();
    }

    public int GetInt(int index)
    {
        return GetVariant(index).GetInt32();
    }

    public long GetLong(int index)
    {
        return GetVariant(index).GetInt64();
    }

    public sbyte GetInt8(int index)
    {
        return GetVariant(index).GetInt8();
    }

    public object GetNull(int index)
    {
        return GetVariant(index).GetNull();
    }


    public string GetString(int index)
    {
        return GetVariant(index).GetString();
    }

    public ushort GetUInt16(int index)
    {
        return GetVariant(index).GetUInt16();
    }

    public uint GetUInt32(int index)
    {
        return GetVariant(index).GetUInt32();
    }

    public ulong GetUInt64(int index)
    {
        return GetVariant(index).GetUInt64();
    }

    public byte GetUInt8(int index)
    {
        return GetVariant(index).GetUInt8();
    }


    public Action GetAction(int index)
    {
        return GetVariant(index).GetAction();
    }
    public object GetObject(int index)
    {
        return GetVariant(index).GetNull();
    }

    public string GetValueToString(int index)
    {
        return GetVariant(index).ToString();
    }

    public void Reset()
    {
        bufArr.Clear();
        Position = 0;
    }

    public void AddBool(bool val)
    {
        bufArr.Add(Variant.MakeForBool(val));
    }

    public void AddDouble(double val)
    {
        bufArr.Add(Variant.MakeForDouble(val));
    }

    public void AddFloat(float val)
    {
        bufArr.Add(Variant.MakeForFloat(val));
    }

    public void AddInt16(short val)
    {
        bufArr.Add(Variant.MakeForInt16(val));
    }

    public void AddInt32(int val)
    {
        bufArr.Add(Variant.MakeForInt32(val));
    }

    public void AddInt(int val)
    {
        bufArr.Add(Variant.MakeForInt32(val));
    }

    public void AddLong(long val)
    {
        bufArr.Add(Variant.MakeForInt64(val));
    }

    public void AddInt64(long val)
    {
        bufArr.Add(Variant.MakeForInt64(val));
    }

    public void AddInt8(sbyte val)
    {
        bufArr.Add(Variant.MakeForInt8(val));
    }

    public void AddNull()
    {
        bufArr.Add(Variant.None);
    }


    public void AddVariant(Variant val)
    {
        bufArr.Add(val);
    }

    public void AddString(string val)
    {
        bufArr.Add(Variant.MakeForString(val));
    }

    public void AddObject(object val)
    {
        bufArr.Add(Variant.MakeForObject(val));
    }

    public void AddUInt16(ushort val)
    {
        bufArr.Add(Variant.MakeForUint16(val));
    }

    public void AddUInt32(uint val)
    {
        bufArr.Add(Variant.MakeForUint32(val));
    }

    public void AddUInt64(ulong val)
    {
        bufArr.Add(Variant.MakeForUint64(val));
    }

    public void AddByte(byte val)
    {
        bufArr.Add(Variant.MakeForUint8(val));
    }

    public void AddUInt8(byte val)
    {
        bufArr.Add(Variant.MakeForUint8(val));
    }

    public void AddVarlist(QuickVarList val)
    {
        bufArr.AddRange(val.bufArr);
    }
    public void AddAction(Action val)
    {
        bufArr.Add(Variant.MakeForAction(val));
    }
    public void AddList<T>(IList<T> val)
        where T : class
    {
        for (int i = 0; i < val.Count; ++i)
        {
            bufArr.Add(Variant.MakeForObject(val[i]));
        }
    }

    public void Add(bool val)
    {
        bufArr.Add(Variant.MakeForBool(val));
    }

    public void Add(double val)
    {
        bufArr.Add(Variant.MakeForDouble(val));
    }

    public void Add(float val)
    {
        bufArr.Add(Variant.MakeForFloat(val));
    }

    public void Add(short val)
    {
        bufArr.Add(Variant.MakeForInt16(val));
    }

    public void Add(int val)
    {
        bufArr.Add(Variant.MakeForInt32(val));
    }

    public void Add(long val)
    {
        bufArr.Add(Variant.MakeForInt64(val));
    }

    public void Add(sbyte val)
    {
        bufArr.Add(Variant.MakeForInt8(val));
    }

    public void Add(Variant val)
    {
        bufArr.Add(val);
    }

    public void Add(string val)
    {
        bufArr.Add(Variant.MakeForString(val));
    }

    public void Add(ushort val)
    {
        bufArr.Add(Variant.MakeForUint16(val));
    }

    public void Add(uint val)
    {
        bufArr.Add(Variant.MakeForUint32(val));
    }

    public void Add(ulong val)
    {
        bufArr.Add(Variant.MakeForUint64(val));
    }

    public void Insert(int index, Variant var)
    {
        bufArr.Insert(index, var);
    }

    public void Add(byte val)
    {
        bufArr.Add(Variant.MakeForUint8(val));
    }

    public void Add(Action val)
    {
        bufArr.Add(Variant.MakeForAction(val));
    }
    public sbyte ReadNextInt8()
    {
        return ReadInt8(Position++);
    }

    public short ReadNextInt16()
    {
        return ReadInt16(Position++);
    }

    public int ReadNextInt32()
    {
        return ReadInt32(Position++);
    }

    public long ReadNextInt64()
    {
        return ReadInt64(Position++);
    }

    public byte ReadNextUInt8()
    {
        return ReadUInt8(Position++);
    }

    public ushort ReadNextUInt16()
    {
        return ReadUInt16(Position++);
    }

    public uint ReadNextUInt32()
    {
        return ReadUInt32(Position++);
    }

    public ulong ReadNextUInt64()
    {
        return ReadUInt64(Position++);
    }

    public float ReadNextFloat()
    {
        return ReadFloat(Position++);
    }

    public double ReadNextDouble()
    {
        return ReadDouble(Position++);
    }

    public bool ReadNextBool()
    {
        return ReadBool(Position++);
    }

    public string ReadNextString()
    {
        return ReadString(Position++);
    }

    public object ReadNextNull()
    {
        return ReadNull(Position++);
    }

    public Variant ReadNextVariant()
    {
        return GetVariant(Position++);
    }

}

